#!/usr/bin/python

"""
EffeLogger - Logger for your effectiveness
Copyright 2009 Mikhail Murzin

Version: 0.1

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License 
version 2 as published by the Free Software Foundation.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
"""

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys

AppName = 'EffeLogger'
ConfigDir = QDir.homePath() + '/.config/' + QString(AppName).toLower()

def monthToFloat(month, year) :
	return year + month / 100.

class Data :
	def __init__ (self):
		self.__data = dict()
		self.__read()

	def __del__ (self) :
		print 'a'

	def __read (self) :
		file = QFile(ConfigDir + '/data')
		if file.open(QIODevice.ReadOnly) :
			while not file.atEnd() :
				line = QString.fromLocal8Bit(file.readLine().data()).simplified()
				list = line.split('|')
				if list.count() < 2 :
					continue
				date = QDate.fromString(list[0], "dd.MM.yyyy")
				mark = list[1].toFloat()[0]
				self.__data[date.toJulianDay()] = mark
			file.close()

	def __save (self) :
		file = QFile(ConfigDir + '/data')
		if file.open(QIODevice.WriteOnly) :
			for index, mark in self.__data.items() :
				str = QDate.fromJulianDay(index).toString("dd.MM.yyyy") + "|" \
						+ QString.number(round(mark, 2)) + "\n"
				file.write(str.toLocal8Bit())
			file.close()

	def firstMonth(self) :
		if len(self.__data) > 0 :
			keys = self.__data.keys()
			keys.sort()
			date = QDate.fromJulianDay(keys[0])
			return date.month(), date.year()
		else :
			date = QDate.currentDate()
			return date.month(), date.year()

	def dayMark(self, day, month, year) :
		index = QDate(year, month, day).toJulianDay()
		if index in self.__data :
			return self.__data[index]
		else :
			return -1
	
	def setDayMark(self, jDay, mark) :
		self.__data[jDay] = mark
		self.__save()

class LoggerArea (QWidget) :
	def __init__ (self) :
		QWidget.__init__(self)
		
		self.data = Data()

		# parameters of painting
		self.mLeft = 2
		self.mRight = 2
		self.mTop = 20
		self.mBottom = 2
		self.dateWidth = 100
		self.cellSize = 20
		
		# colors
		self.mainColor = QColor(50, 50, 100)
		self.bgColor = QColor(220, 220, 220)

		# limits
		self.firstMonth, self.firstYear = self.data.firstMonth()
		self.lastYear = self.firstYear + 5
		self.lastMonth = self.firstMonth
		
		months = (self.lastYear - self.firstYear)*12 + (self.lastMonth - self.firstMonth) + 1
		
		self.resize(self.mLeft + self.mRight + self.dateWidth + 31 * self.cellSize, 800)
		self.setMinimumWidth(self.mLeft + self.mRight + self.dateWidth + 31 * self.cellSize)
		self.setMinimumHeight(self.mTop + self.mBottom + months * self.cellSize)
		
		#	cell menu
		self.dayMenu = QMenu()
		self.dayMenu.addAction("0%", self.markDayWith)
		self.dayMenu.addAction("50%", self.markDayWith)
		self.dayMenu.addAction("100%", self.markDayWith)
		
		self.curDay = -1

	def startingMonth(self) :
		return self.firstMonth, self.firstYear

	def dayColor(self, day, month, year) :
		mark = self.data.dayMark(day, month, year)
		if mark < 0 :
			return self.bgColor
		else :
			r = self.mainColor.red()
			g = self.mainColor.green()
			b = self.mainColor.blue()
			return QColor( 255 - mark*(255 - r), 255 - mark*(255 - g), 255 - mark*(255 - b) )

	def markDayWith(self) :
		text = self.sender().text()
		text.chop(1)	# removing '%' symbol
		mark = text.toInt()[0] / 100.
		self.data.setDayMark(self.curDay, mark)
		self.curDay = -1
		self.update()

	def mouseReleaseEvent(self, event) :
		x = event.x()
		y = event.y()
		dMonths = (y - self.mTop) / self.cellSize
		if dMonths < 0 :
			return
		dYears = dMonths / 12
		year = self.firstYear + dYears
		month = self.firstMonth + (dMonths - dYears*12)
		if ( month > 12 ) :
			month = month - 12
			year = year + 1
		day = (x - self.mLeft - self.dateWidth) / self.cellSize + 1
		date = QDate(year, month, 1)
		if day <= 0 or day > date.daysInMonth() :
			return

		date = date.addDays(day - 1)

		print day, month, year, "-", date.toJulianDay()

		# popup menu
		self.curDay = date.toJulianDay()
		self.dayMenu.popup(event.globalPos())

	def paintEvent(self, event) :
		p = QPainter(self)
		p.setBrush(self.bgColor)
		w = self.width()
		h = self.height()
		ww = w - self.mLeft - self.mRight
		hh = h - self.mTop - self.mBottom

		p.drawRect(self.mLeft, self.mTop, ww, hh)
		
		# draw days
		x = self.mLeft + self.dateWidth
		sz = self.cellSize
		for d in range(1, 32) :
			p.drawText(x, 0, sz, self.mTop, Qt.AlignCenter | Qt.AlignVCenter, QString.number(d))
			x += sz
		
		# draw everything else
		month, year = self.startingMonth()
		curDate = monthToFloat(month, year)
		lastDate = monthToFloat(self.lastMonth, self.lastYear)
		y = self.mTop
		
		p.drawLine(self.mLeft + self.dateWidth, self.mTop, self.mLeft + self.dateWidth, self.mTop + hh)
		while curDate <= lastDate :
			# draw months
			date = QDate(year, month, 1)
			str = date.toString("MMM yyyy")
			p.drawText(self.mLeft, y, self.dateWidth - 2, self.cellSize, Qt.AlignRight | Qt.AlignVCenter, str)
			
			# draw cells
			days = date.daysInMonth()
			for day in range(0, days) :
				color = self.dayColor(day + 1, month, year)
				p.setBrush(color)
				p.drawRect(self.mLeft + self.dateWidth + day * self.cellSize + 2, 
						y + 2, self.cellSize - 4, self.cellSize - 4)

			month += 1
			if month == 13 :
				month = 1
				year += 1
			y += self.cellSize
			curDate = monthToFloat(month, year)

class MW (QScrollArea) :
	def __init__ (self) :
		QScrollArea.__init__(self)
		self.setWindowTitle(AppName)
		self.setWidgetResizable(True)
		self.logger = LoggerArea()
		self.setWidget(self.logger)
		self.logger.show()

if __name__ == '__main__' :
	if not QDir(ConfigDir).exists() :
		QDir().mkpath(ConfigDir)

	app = QApplication(sys.argv)
	mw = MW()
	mw.resize(750, 500)
	mw.show()
	app.exec_()
